#include <Arduino.h>
#include "CircularBuffer.h"
#include "I2CSlave.h"
#include "SWMonitor.h"

#include "DataStorage.h"

#include "CmdLine.h"
#include "TimeOut.h"
#include "PwmS5Controller.h"

#include "DigitalOut.h"
#include "PwmOut.h"
#include "PwmS5.h"

#include "log.h"
#include "lwmp.h"

// put function declarations here:
//"PD3",TIMER2B);
//"PB2",TIMER1B);
//"PD5",TIMER0B);
//"PB1",TIMER1A);
//"PB3",TIMER2A);

// PwmOut _r(PD_3);
// PwmOut _g(PB_2);
// PwmOut _b(PD_5);

// PwmOut _w(PB_1);
// PwmOut _y(PB_3);

// CmdLine cmdline;

Mail<> mb;

I2CSlave i2c_slave(mb);

DataStorage dataStorage(mb);

SW1248 sw1248;

SWMonitor sw_monitor(sw1248);

Timeout data_monitor_timeout;

Timeout sw_monitor_timeout;

PwmS5 pwmS5(PD_3,PB_2,PD_5,PB_1,PB_3);

PwmS5Controller pwmS5Controller(i2c_slave,dataStorage,pwmS5);

Scheduler* scheduler_tasks[]={
  //&cmdline,             //添加任务0: 接收命令         (Y)
  &sw1248,              //添加任务1: 按键扫描         (Y)
  &sw_monitor,          //添加任务2: 按键状态检测     (Y)
  &sw_monitor_timeout,  //添加任务3: 超时任务         (Y)
  &data_monitor_timeout,//添加任务4: 超时任务         (Y)
  &pwmS5Controller      //添加任务5: 系统控制         (Y)
};

//PWM_SW_5 模块支持两种工作模式：选择频率 和 自定义频率 两种模式可供选择
//本模块带有4种状态和2种模式, 用户可以很方便的在不同的状态之间进行切换, 长按可以关闭或打开此状态.

//默认寄存器地址范围: 0x02[0x44],0x03[0x45],0x04[0x46] 和 0x05[0x47], 这些地址保持了模块的状态信息. 间隔一段时间后, 会自动保存到 EEPROM 中.
void setup() {

  // put your setup code here, to run once:

  // start serial for output 
  Serial.begin(9600);    
  log::debug("Atmega328p:serial begin\r\n");

  // // start sw1248 
  sw1248.begin();
  log::debug("sw1248 begin:0x%x\r\n",sw1248.state().value);
  sw_monitor.attach([]{
    //检测到地址发生改变，设置超时后更新I2C地址
    sw_monitor_timeout.attach([]{
      i2c_slave.begin(sw1248.state().value);
      log::debug("i2c begin new addr:%x\r\n",sw1248.poll());
      sw_monitor_timeout.detach();
    },8);
  });
  

  // start data storage 
  dataStorage.begin();
  log::debug("ds begin:0x%x\r\n",dataStorage.read_data_storage_eof());

  // start i2c
  i2c_slave.begin(sw1248.state().value);
  log::debug("i2c begin:%x\r\n",sw1248.state().value);

  
  i2c_slave.on_request([]{
    //返回主机请求的数据
    data_storage_reg_read_t& reg = dataStorage.get_reg_data(i2c_slave.get_reg_read_address());
    i2c_slave.write((const uint8_t *)reg.data,reg.size);
  });

  i2c_slave.on_receive([](int howMany){
    //处理主机发送的数据
      i2c_slave.handle_on_receive(howMany);
      data_monitor_timeout.attach(&dataStorage,&DataStorage::check_update,30);
  });

  pwmS5Controller.begin();
  log::debug("run tasks\r\n");

}

void loop() {
  // put your main code here, to run repeatedly:
  for(uint8_t i=0;i<sizeof(scheduler_tasks)/sizeof(Scheduler*);i++){
    scheduler_tasks[i]->schedule();
  }
}

void serialEvent() {
  // 当接收到数据时，这个函数会被自动调用
  // cmdline.cleanup();
  // while (Serial.available()) {
  //   char inChar = (char)Serial.read(); // 读取一个字节的数据
  //   cmdline.append(inChar);
  // }
  // cmdline.update();
}